﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
//MicroDesigner
using Jc.MicroDesigner.Management;
using Jc.MicroDesigner.Objects;

namespace Jc.MicroDesigner.ToolWindows
{
    /// <summary>
    /// Форма для выбора элементов и пинов, которые следует добавить в окно слежения за сигналами
    /// </summary>
    public partial class WatchListForm : Form
    {
        #region Структуры для скрытия checkbox у первого уровня Узлов
        // constants used to hide a checkbox
        public const int TVIF_STATE = 0x8;
        public const int TVIS_STATEIMAGEMASK = 0xF000;
        public const int TV_FIRST = 0x1100;
        public const int TVM_SETITEM = TV_FIRST + 63;

        [DllImport("user32.dll")]
        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam,
        IntPtr lParam);

        // struct used to set node properties
        public struct TVITEM
        {
            public int mask;
            public IntPtr hItem;
            public int state;
            public int stateMask;
            [MarshalAs(UnmanagedType.LPTStr)]
            public String lpszText;
            public int cchTextMax;
            public int iImage;
            public int iSelectedImage;
            public int cChildren;
            public IntPtr lParam;
        }

        /// <summary>
        /// Скрыть Checkbox для узла
        /// </summary>
        /// <param name="node">Узел</param>
        void HideCheckBox(TreeNode node)
        {
            TVITEM tvi = new TVITEM();
            tvi.hItem = node.Handle;
            tvi.mask = TVIF_STATE;
            tvi.stateMask = TVIS_STATEIMAGEMASK;
            tvi.state = 0;
            IntPtr lparam = Marshal.AllocHGlobal(Marshal.SizeOf(tvi));
            Marshal.StructureToPtr(tvi, lparam, false);
            SendMessage(this.ElementsTree.Handle, TVM_SETITEM, IntPtr.Zero, lparam);
        }

        void ElementsTree_DrawNode(object sender, DrawTreeNodeEventArgs e)
        {
            if (e.Node.Level == 0)
                HideCheckBox(e.Node);
            e.DrawDefault = true;
        }

        #endregion

        private ObjectManager _Manager = null;
        private TreeNode _Selected = null;

        public WatchListForm()
        {
            InitializeComponent();
            this.ElementsTree.DrawMode = TreeViewDrawMode.OwnerDrawText;
            this.ElementsTree.DrawNode += new DrawTreeNodeEventHandler(ElementsTree_DrawNode);
        }

        /// <summary>
        /// Показать диалог для текущей схемы
        /// </summary>
        /// <param name="manager">логическая схема</param>
        public void Show(ObjectManager manager)
        {
            _Manager = manager;
            if (manager != null)
            {
                foreach (BaseElement item in manager.Elements)
                {
                    if ((item is CircuitElement) && !(item is Wire) && !(item is Node))
                    {
                        CircuitElement ce = item as CircuitElement;
                        TreeNode node = new TreeNode(ce.Name);
                        //сохраняем данные в элемент
                        node.Tag = ce;
                        //добавить иконку
                        node.ImageIndex = 0;
                        node.SelectedImageIndex = 0;
                        foreach (PIN pin in ce.PINs)
                        {
                            TreeNode pnode = new TreeNode(pin.Name + ":" + pin.TypeToString());
                            //сохраняем данные в элемент
                            int j = 0;
                            while ((j < _Manager.Watches.Count) && (_Manager.Watches[j].Source != pin))
                                j++;
                            if (j < _Manager.Watches.Count)
                            {
                                pnode.Tag = _Manager.Watches[j];
                                pnode.Checked = true;
                                pnode.Text += " = " + _Manager.Watches[j].Label;
                            }
                            else
                                pnode.Tag = new SignalContainer(pin, 0);

                            //добавить иконку
                            pnode.ImageIndex = 1;
                            pnode.SelectedImageIndex = 1;
                            node.Nodes.Add(pnode);
                        }
                        ElementsTree.Nodes.Add(node);
                    }
                }
            }
            ShowDialog();
        }

        #region Events
        private void ElementsTree_AfterSelect(object sender, TreeViewEventArgs e)
        {
            _Selected = null;
            WatchProperty.SelectedObject = null;
            groupBox1.Enabled = e.Node.Checked;
            if (e.Node.Level == 1)
            {
                WatchProperty.SelectedObject = e.Node.Tag;
                _Selected = e.Node;
            }
        }

        private void ElementsTree_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (ElementsTree.SelectedNode != e.Node)
                ElementsTree.SelectedNode = e.Node;

            groupBox1.Enabled = e.Node.Checked;
            if (e.Node.Level == 1)
            {
                SignalContainer sc = e.Node.Tag as SignalContainer;
                WatchProperty.SelectedObject = e.Node.Tag;
                //LabelTxtBox.Text = sc.Label;
                PIN pin = sc.Source as PIN;
                e.Node.Text = pin.Name + ":" + pin.TypeToString();
                if (e.Node.Checked)
                {
                    if (!String.IsNullOrEmpty(sc.Label))
                        e.Node.Text += " = " + sc.Label;
                }
            }
        }

        private void OKBtn_Click(object sender, EventArgs e)
        {
            //сохраняем наблюдаемые элементы в _Manager.Watches
            _Manager.Watches.Clear();
            for (int i = 0; i < ElementsTree.Nodes.Count; i++)
            {
                for (int j = 0; j < ElementsTree.Nodes[i].Nodes.Count; j++)
                {
                    if (ElementsTree.Nodes[i].Nodes[j].Checked)
                    {
                        SignalContainer container = ElementsTree.Nodes[i].Nodes[j].Tag as SignalContainer;
                        _Manager.Watches.Add(container);
                    }
                }
            }
        }

        private void ElementsTree_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                ElementsTree.SelectedNode = e.Node;
            }
        }

        private void WatchProperty_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            if (_Selected != null)
            {
                SignalContainer sc = _Selected.Tag as SignalContainer;
                PIN pin = sc.Source as PIN;
                _Selected.Text = pin.Name + ":" + pin.TypeToString();
                if (!String.IsNullOrEmpty(sc.Label))
                    _Selected.Text += " = " + sc.Label;
            }
        }
        #endregion
    }
}